package waal.pc.frontend.tiles;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JLabel;

import waal.pc.backend.Log;
import waal.pc.backend.channels.Channel;
import waal.pc.backend.channels.ChannelChangeListener;
import waal.pc.backend.channels.DigitalChannel;
import waal.pc.backend.channels.DigitalOutputChannel;
import waal.pc.backend.module.Module;
import waal.pc.backend.module.ModuleDigital;
import waal.pc.frontend.Surface;

public class DigitalIOTile extends ModuleTile implements ChannelChangeListener, ActionListener {

	private static final long serialVersionUID = -7820137326251284945L;
	private GridBagLayout gbl;
	private Map<Integer, JLabel> inputChannels; 
	private Map<Integer, DigitalOutputChannel> outputChannels;
	private Map<Integer, JButton> outputChannelsButtons;
	
	public DigitalIOTile() {
		super("DigitalIO");
		
		this.gbl = new GridBagLayout();
		this.setLayout(this.gbl);
	}
	
	@Override
	public Tile getTile(Module module) {
		this.initTile(module);
		this.inputChannels = new HashMap<Integer, JLabel>();
		this.outputChannels = new HashMap<Integer, DigitalOutputChannel>();
		this.outputChannelsButtons = new HashMap<Integer, JButton>();
		ModuleDigital m = (ModuleDigital) module;
		int row = 0;
		
		Channel c;
		JLabel label, value;
		JButton action;
		this.addComponent(new JLabel(module.getName()), 		0, row++, 2, 1, 1, 0);
		for(Iterator<Channel> it = m.getChannels().iterator(); it.hasNext(); ) {
			c = it.next();
			label = new JLabel(c.toString());
			this.addComponent(label, 							0, row, 1, 1, 1, 0);
			if(c.isInput()) {
				Log.addToDebug(3, "DigitalIOTile", "getTile", "New  input channel: " + c.getChannelNumber());
				DigitalChannel icd =  (DigitalChannel) c;
				icd.addListener(this);
				if(icd.getLastState()) {
					value = new JLabel("on");
				} else {
					value = new JLabel("off");
				}
				this.inputChannels.put(c.getChannelNumber(), value);
				this.addComponent(value,					 	1, row++, 1, 1, 1, 0);
			} else {
				Log.addToDebug(3, "DigitalIOTile", "getTile", "New output channel: " + c.getChannelNumber());
				DigitalOutputChannel ocd = (DigitalOutputChannel) c; 
				ocd.addListener(this);
				System.out.println("Channel: " + ocd.getChannelNumber());
				this.outputChannels.put(ocd.getChannelNumber(), ocd);
				
				if(ocd.getLastState()) {
					action = new JButton("on->off");
				} else {
					action = new JButton("off->on");
				}
				action.addActionListener(this);
				action.setActionCommand("" + c.getChannelNumber());
				this.outputChannelsButtons.put(ocd.getChannelNumber(), action);
				this.addComponent(action,					 	1, row++, 1, 1, 1, 0);
			}
		}
		
		
		return this;
	}
	
	private void addComponent(Component c, int x, int y, int width, int height, double weightx, double weighty ) {
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = x; gbc.gridy = y;
		gbc.gridwidth = width; gbc.gridheight = height;
		gbc.weightx = weightx; gbc.weighty = weighty;
		gbc.ipadx = 10; gbc.ipady = 5;
		this.gbl.setConstraints( c, gbc );
		c.setPreferredSize(new Dimension(Surface.tile_x, Surface.tile_y));
		this.add( c );

	}

	@Override
	public boolean isDigital() {
		return true;
	}

	@Override
	public boolean isInput() {
		return true;
	}

	@Override
	public boolean isOutput() {
		return true;
	}

	@Override
	public boolean isUpdateAble() {
		return false;
	}


	@Override
	public void actionPerformed(ActionEvent e) {
		int channelNumber = Integer.parseInt(e.getActionCommand());
		//Log.addToDebug(3, "DigitalIOTile", "actionPerformed", "Button Press for channel " + channelNumber + "command: " + e.getActionCommand());
			DigitalOutputChannel ch = this.outputChannels.get(channelNumber);
		if(ch != null) {
			Log.addToDebug(3, "DigitalIOTile", "actionPerformed", "Button Press for channel " + channelNumber + " command: " + e.getActionCommand());
			ch.toggleChannel();
		} else {
			Log.addToDebug(3, "DigitalIOTile", "actionPerformed", "no Channel");
		}
	}

	@Override
	public ModuleTile clone() {
		return new DigitalIOTile();
	}

	@Override
	public void updateFormChannel(int number, Channel ch) {
		DigitalChannel dch = (DigitalChannel) ch;
		if(dch.isInput()) {
			if(dch.getLastState()) {
				this.inputChannels.get(number).setText("on");
			} else {
				this.inputChannels.get(number).setText("off");
			}
		} else {
			if(dch.getLastState()) {
				this.outputChannelsButtons.get(number).setText("on->off");
			} else {
				this.outputChannelsButtons.get(number).setText("off->on");
			}
		}
	}

	@Override
	public void channelGetKilled(Channel ch) {
		this.inputChannels.remove(ch.getChannelNumber());		
	}

	@Override
	public void closeTile() {
		this.outputChannels.clear();
		
	}

	@Override
	protected void hubStart() {
				
	}

	@Override
	protected void hubStop() {
				
	}

	@Override
	public void setDimension(int width, int heigh) {
				
	}

	

}
